package de.tu_darmstadt.gdi1.xcom.tests.testcases.students;

import static org.junit.Assert.*;
import java.util.LinkedList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

import de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel1;

/**
 * 
 * Tests, whether the game implements the check for syntactical correctness the right way.
 * 
 * @author Lukas Schwoebel
 *
 */
public class IsCorrectLevelTest {
	
	private XcomTestAdapterLevel1 testAdapter;
	
	private List<String> correctLevels;
	private List<String> falseLevels;
	
	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		testAdapter = new XcomTestAdapterLevel1();
		correctLevels = new LinkedList<String>();
		correctLevels.add("" +
				"############\n" +
				"##...#######\n" +
				"##...##..+##\n" +
				"###.###...##\n" +
				"###.####.###\n" +
				"#....##...##\n" +
				"#.........##\n" +
				"############\n" +
				"//{mobs}\n" +
				"//@;4;2;n;50;75;50;50;10\n" +
				"//@;2;5;n;50;75;50;50;10\n" +
				"//@;4;6;n;50;75;50;50;10\n" +
				"//Z;2;2;n;50;75;50;50;0\n" +
				"//Z;3;2;n;50;75;50;50;0\n" +
				"//Z;7;3;n;50;75;50;50;0\n" +
				"//Z;7;5;n;50;75;50;50;0\n" +
				"//Z;9;6;n;50;75;50;50;0\n" +
				"//{doors}\n" +
				"//1;4;8;4;c");
		correctLevels.add("" +
				"####\n" +
				"#..#\n" +
				"##.#\n" +
				"####\n" +
				"//{mobs}\n" +
				"//@;2;1;n;50;75;50;50;10\n" +
				"//Z;1;1;n;50;75;50;50;10");
		correctLevels.add("" +
				"#####\n" +
				"#..##\n" +
				"#.###\n" +
				"##.##\n" +
				"#####\n" +
				"//{mobs}\n" +
				"//@;1;2;n;50;75;50;50;10\n" +
				"//Z;1;1;n;50;75;50;50;10\n" +
				"//{doors}\n" +
				"//2;2;2;3;c");
		correctLevels.add("" +
				"#####\n" +
				"###.#\n" +
				"#.#.#\n" +
				"##.##\n" +
				"#####\n" +
				"//{mobs}\n" +
				"//@;3;2;n;50;75;50;50;10\n" +
				"//{doors}\n" +
				"//2;2;2;3;c\n" +
				"//1;3;3;1;c");

		falseLevels = new LinkedList<String>();
		// no surrounding walls
		falseLevels.add("" +
				".....\n" +
				"###.#\n" +
				"#.#.#\n" +
				"##.##\n" +
				"#####\n" +
				"//{mobs}\n" +
				"//@;0;0;n;50;75;50;50;10\n" +
				"//{doors}\n" +
				"//2;2;2;3;c\n" +
				"//1;3;2;3;c");
		// invalid characters
		falseLevels.add("" +
				"##l##\n" +
				"##e.#\n" +
				"#.e.#\n" +
				"##t##\n" +
				"#####\n" +
				"//{mobs}\n" +
				"//@;3;1;n;50;75;50;50;10\n" +
				"//{doors}\n" +
				"//3;1;3;2;c");
		// no player/mob in level at all
		falseLevels.add("" +
				"####\n" +
				"#..#\n" +
				"##.#\n" +
				"####");
		// no human in level
		falseLevels.add("" +
				"####\n" +
				"#..#\n" +
				"##.#\n" +
				"####\n" +
				"//{mobs}\n" +
				"//Z;1;1;n;50;75;50;50;10");
		// player put on wall
		falseLevels.add("" +
				"####\n" +
				"#..#\n" +
				"##.#\n" +
				"####\n" +
				"//{mobs}\n" +
				"//@;0;0;n;50;75;50;50;10\n" +
				"//{doors}\n" +
				"//1;2;2;1;c");
	}

	/**
	 * Test method for {@link de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel1#isCorrectLevel()}.
	 */
	@Test
	public final void testIsCorrectLevel() {
		int i;
		i = 0;
		for (String level : correctLevels) {
			//this.testAdapter.loadLevelFromString(level);
			assertTrue("Your implementation identified a correct level as incorrect, list-index: " + i, 
					testAdapter.isCorrectLevel(level));
			i++;
		}
		i = 0;
		for (String level : falseLevels) {
			//this.testAdapter.loadLevelFromString(level);
			assertFalse("Your implementation identified an incorrect level as correct, list-index: " + i, 
					testAdapter.isCorrectLevel(level));
			i++;
		}
	}

	/**
	 * Test method for {@link de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel1#elementOnPosition(x,y)}.
	 */
	@Test
	public final void testIsCorrectInterpreted() {
		// get first element
		String level = correctLevels.get(0);
		testAdapter.loadLevelFromString(level);
		// now simply check if elements were correctly interpreted
		assertTrue("Your implementation did not interpret the level correctly, on 2:1 should be a floor",
				(testAdapter.elementOnPosition(2, 1) == '.'));
		assertTrue("Your implementation did not interpret the level correctly, on 5:0 should be a wall",
				(testAdapter.elementOnPosition(5, 0) == '#'));
		assertTrue("Your implementation did not interpret the level correctly, on 4:2 should be a player",
				(testAdapter.elementOnPosition(4, 2) == '@'));
		assertTrue("Your implementation did not interpret the level correctly, on 3:2 should be an alien",
				(testAdapter.elementOnPosition(3, 2) == 'Z'));
		assertTrue("Your implementation did not interpret the level correctly, on 3:2 should be an alien",
				(testAdapter.elementOnPosition(3, 2) == 'Z'));
		assertTrue("Your implementation did not interpret the level correctly, on 1:4 should be a wall or a switch",
				(testAdapter.elementOnPosition(1, 4) == 'c' || testAdapter.elementOnPosition(1, 4) == '#'));
		assertTrue("Your implementation did not interpret the level correctly, on 8:4 should be a floor or a door",
				(testAdapter.elementOnPosition(8, 4) == '=' || testAdapter.elementOnPosition(8, 4) == '.'));
	}

	/**
	 * Test method for {@link de.tu_darmstadt.gdi1.xcom.tests.adapters.XcomTestAdapterLevel1#elementOnPosition(x,y)}.
	 */
	@Test
	public final void testIsCorrectHandled() {
		// get first element
		String level = correctLevels.get(0);
		testAdapter.loadLevelFromString(level);
		
		// now walk a little and check if the level is really interpreted correctly
		// NOTE: this is not a replacement for testing if actions are handled correctly!
		
		// check if there is a player on 4:2
		assertTrue("Your implementation did not interpret the level correctly, on 4:2 should be a player",
				(testAdapter.elementOnPosition(4, 2) == '@'));
		// now move first player up, should leave a floor-element
		testAdapter.performActionForActivePlayer();
		assertTrue("After moving, the player should leave floor and 4:2",
				(testAdapter.elementOnPosition(4, 2) == '.'));
		assertTrue("After moving, the player should be on 4:1",
				(testAdapter.elementOnPosition(4, 1) == '@'));
	}
}
